package com.zzl.study.nacos.discovery;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * Nacos多注册中心服务发现客户端
 *
 * @author: zhangzl
 * @date: 2025/7/16 11:43
 * @version: 1.0
 */
@Slf4j
public class NacosMultiDiscoveryClient implements DiscoveryClient {

    /**
     * 服务发现客户端描述
     */
    public static final String DESCRIPTION = "Spring Cloud Nacos Multiple Discovery Client";

    /**
     * 失败容错开关
     */
    @Value("${spring.cloud.nacos.multi-discovery.failure-tolerance-enabled:false}")
    private boolean failureToleranceEnabled;

    /**
     * Nacos多注册中心服务发现对象
     */
    private final NacosServiceMultiDiscovery nacosServiceMultiDiscovery;

    /**
     * 构造函数
     *
     * @param nacosServiceMultiDiscovery Nacos多注册中心服务发现对象
     */
    public NacosMultiDiscoveryClient(NacosServiceMultiDiscovery nacosServiceMultiDiscovery) {
        this.nacosServiceMultiDiscovery = nacosServiceMultiDiscovery;
    }

    @Override
    public String description() {
        return DESCRIPTION;
    }

    @Override
    public List<ServiceInstance> getInstances(String serviceId) {
        try {
            return Optional.of(this.nacosServiceMultiDiscovery.getInstances(serviceId))
                    .map(instances -> {
                        ServiceCache.setInstances(serviceId, instances);
                        return instances;
                    }).get();
        } catch (Exception e) {
            if (failureToleranceEnabled) {
                return ServiceCache.getInstances(serviceId);
            }
            throw new RuntimeException("Can not get hosts from nacos server. serviceId: " + serviceId, e);
        }
    }

    @Override
    public List<String> getServices() {
        try {
            return Optional.of(this.nacosServiceMultiDiscovery.getServices()).map(services -> {
                ServiceCache.setServiceIds(services);
                return services;
            }).get();
        } catch (Exception e) {
            log.error("get service name from nacos server failed.", e);
            return failureToleranceEnabled ? ServiceCache.getServiceIds() : Collections.emptyList();
        }
    }

}
